package com.blueocean_health.care.management.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.blueocean_health.care.management.common.LocalManager;
import com.blueocean_health.care.management.common.base.string.StringUtils;
import com.blueocean_health.care.management.domain.base.Power;
import com.blueocean_health.care.management.domain.base.Role;
import com.blueocean_health.care.management.domain.base.RolePower;
import com.blueocean_health.care.management.domain.base.SysResult;
import com.blueocean_health.care.management.domain.base.SysResultByPage;
import com.blueocean_health.care.management.domain.base.Team;
import com.blueocean_health.care.management.domain.base.UserTeam;
import com.blueocean_health.care.management.domain.dto.RoleDto;
import com.blueocean_health.care.management.domain.dto.RoleListDto;
import com.blueocean_health.care.management.domain.vo.LoginDataVo;
import com.blueocean_health.care.management.domain.vo.RoleVo;
import com.blueocean_health.care.management.em.LocalManagerType;
import com.blueocean_health.care.management.em.ProjectManagerKeyEnum;
import com.blueocean_health.care.management.em.ProjectTypeEnum;
import com.blueocean_health.care.management.mapper.PowerMapper;
import com.blueocean_health.care.management.mapper.RoleMapper;
import com.blueocean_health.care.management.mapper.RolePowerMapper;
import com.blueocean_health.care.management.mapper.TeamMapper;
import com.blueocean_health.care.management.mapper.UserTeamMapper;
import com.blueocean_health.care.management.service.RoleService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * 角色service
 * 
 * @author huyanqiu
 * @date 2018年3月23日 下午2:51:52
 * @version 版本号：1.0
 */
@Service
public class RoleServiceImpl implements RoleService {

	@Autowired
	private TeamMapper teamMapper;
	@Autowired
	private RoleMapper roleMapper;
	@Autowired
	private PowerMapper powerMapper;
	@Autowired
	private RolePowerMapper rolePowerMapper;
	@Autowired
	private UserTeamMapper userTeamMapper;

	/**
	 * 创建角色 1. 只能为当前登录人所在组织以及所有下级组织创建角色 2. 通用角色，都能进行授权 3. 通用角色（蓝海创建编辑）&
	 * 非通用角色（各级组织自行创建编辑，上下层级没有继承关系）
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public SysResult add(RoleVo roleVo) {
		// 获得登录人信息
		LoginDataVo loginDataVo = LocalManager.getVal(LocalManagerType.LOGIN_DATA);
		Team team = teamMapper.findOrgById(roleVo.getOrgId());
		if (StringUtils.isEmpty(team) || team.getIsActive() == 3) {
			return SysResult.error("所属组织不存在或已被删除");
		}
		// 判断角色名称唯一(只约束同级)
		RoleVo uniqueRole = roleMapper.findFirstSubRoleByName(roleVo);
		if (!StringUtils.isEmpty(uniqueRole)) {
			return SysResult.error("该角色已存在，请勿重复提交");
		}

		List<Power> allPower = roleMapper.findAllPowerByType(Integer.parseInt(roleVo.getType()));
		Set<String> codes = new HashSet<>();
		// moduleCode 为key， 查询powerCode为value，用来判断添加的权限是否正确
		Map<String, String> checkQuery = new HashMap<>();
		allPower.stream().forEach(p -> {
			codes.add(p.getPowerCode());
			if (p.getPowerName().equals("查询")) {
				checkQuery.put(p.getPowerCode().substring(0, p.getPowerCode().lastIndexOf("-")), p.getPowerCode());
			}
		});

		if (!roleVo.getPermissions().isEmpty()) {
			// 过滤模块
			roleVo.setPermissions(roleVo.getPermissions().stream().filter(p -> {
				return !StringUtils.isEmpty(p) && codes.contains(p);
			}).collect(Collectors.toList()));

			// 在提交时，增加一个判断，若勾选部分权限，未勾选“查询”，
			// 提示“部分模块未勾选查询权限，无法正常使用；请勾选查询权限”
			for (String p : roleVo.getPermissions()) {
				String moduleCode = p.substring(0, p.lastIndexOf("-"));
				if(checkQuery.containsKey(moduleCode) && !roleVo.getPermissions().contains(checkQuery.get(moduleCode))) {
					return SysResult.error("部分模块未勾选查询权限，无法正常使用；请勾选查询权限");
				}
			}
		}

		Role role = new Role();
		role.setRoleName(roleVo.getName());
		role.setTeamId(roleVo.getOrgId());
		role.setIsPublicRole(2);
		role.setIsActive(team.getIsActive());
		role.setCreateBy(loginDataVo.getUser().getUserId());
		role.setType(roleVo.getType());
		role.setFirstOrg(team.getFirstOrg());

		if (ProjectManagerKeyEnum._1.getVal().equals(role.getRoleName())) {
			role.setCategory(ProjectManagerKeyEnum._1.getKey());
		} else if (ProjectManagerKeyEnum._2.getVal().equals(role.getRoleName())) {
			role.setCategory(ProjectManagerKeyEnum._2.getKey());
		} else {
			role.setCategory(null);
		}

		roleVo.setStatus(team.getIsActive());
		// 保存角色基本信息
		int roleNum = roleMapper.addRoleBase(role);
		if (roleNum < 1) {
			return SysResult.error("保存角色基本信息失败");
		}
		if (StringUtils.isEmpty(role.getRoleId())) {
			uniqueRole = roleMapper.findFirstSubRoleByName(roleVo);
			roleVo.setId(uniqueRole.getId());
		} else {
			roleVo.setId(role.getRoleId());
		}

		if (!roleVo.getPermissions().isEmpty()) {
			// 保存角色和权限中间表信息
			int rolePowerNum = rolePowerMapper.addRolePowerBase(roleVo);
			if (rolePowerNum < 1) {
				return SysResult.error("保存角色和权限中间表信息失败");
			}
		}
		return SysResult.ok();
	}

	/**
	 * 编辑角色
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public SysResult modify(RoleVo roleVo) {
		LoginDataVo loginDataVo = LocalManager.getVal(LocalManagerType.LOGIN_DATA);
		Team team = loginDataVo.getCurrentTeam();
		if (StringUtils.isEmpty(team)) {
			return SysResult.error("所属组织不存在");
		}
		if (team.getIsActive() == 2) {
			return SysResult.error("所属组织为禁用状态，无法编辑角色。");
		}
		Role role = roleMapper.selectByPrimaryKey(roleVo.getId());
		if (role.getIsPublicRole() == 1) {
			return SysResult.error("通用角色不能编辑");
		}
		// 判断角色名称唯一(只约束同级)
		RoleVo uniqueRole = roleMapper.findFirstSubRoleByName(roleVo);
		if (!StringUtils.isEmpty(uniqueRole)) {
			return SysResult.error("该角色已存在，请勿重复提交");
		}
		if (!roleVo.getType().equals(role.getType())) {
			List<UserTeam> userTeamList = userTeamMapper.findUserByRoleIdAndStatus(role.getRoleId(),
					String.valueOf(role.getIsActive()));
			if (!userTeamList.isEmpty()) {
				return SysResult.error("该角色已添加用户，现无法修改角色类型。");
			}
		}

		// 更新角色基本信息
		int roleNum = roleMapper.updateRoleByRoleId(roleVo);
		if (roleNum < 1) {
			return SysResult.error("角色基本信息更新失败");
		}

		List<Power> allPower = roleMapper.findAllPowerByType(Integer.parseInt(roleVo.getType()));
		Set<String> codes = new HashSet<>();
		allPower.stream().forEach(p -> codes.add(p.getPowerCode()));
		if (!StringUtils.isEmpty(roleVo.getPermissions())) {
			roleVo.setPermissions(roleVo.getPermissions().stream().filter(p -> {
				return !StringUtils.isEmpty(p) && codes.contains(p);
			}).collect(Collectors.toList()));
		}

		// 查询角色对应的模块
		List<RolePower> rolePowerList = rolePowerMapper.selectByRoleId(roleVo.getId());
		Set<String> removePowerSet = new HashSet<>();
		rolePowerList.forEach(power -> {
			removePowerSet.add(power.getPowerCode());
		});

		Set<String> copySavePowerSet = new HashSet<>(removePowerSet);
		Set<String> addPowerSet = new HashSet<>(roleVo.getPermissions());

		// 需要删除的集合
		removePowerSet.removeAll(addPowerSet);
		// 需要增加的集合
		addPowerSet.removeAll(copySavePowerSet);
		if (!removePowerSet.isEmpty()) {
			int deleteNum = rolePowerMapper.deleteByRoleIdAndPowerCode(roleVo.getId(), removePowerSet);
			if (deleteNum < 1) {
				return SysResult.error("删除失败");
			}
		}
		if (!addPowerSet.isEmpty()) {
			Map<String, Object> paramsMap = new HashMap<>();
			paramsMap.put("status", role.getIsActive());
			paramsMap.put("roleId", role.getRoleId());
			int addNum = rolePowerMapper.addRolePowerByRoleIdAndPowerSet(paramsMap, addPowerSet);
			if (addNum < 1) {
				return SysResult.error("添加失败");
			}
		}
		return SysResult.ok();
	}

	/**
	 * 删除角色
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public SysResult delete(Integer id) {
		Role role = roleMapper.selectByPrimaryKey(id);
		if (StringUtils.isEmpty(role) || role.getIsActive() == 3) {
			return SysResult.error("角色不存在或已被删除");
		}
		if (role.getIsPublicRole() == 1) {
			return SysResult.error("通用角色不能删除");
		}
		List<UserTeam> userTeamList = userTeamMapper.findUserByRoleIdAndStatus(role.getRoleId(),
				String.valueOf(role.getIsActive()));
		if (!userTeamList.isEmpty()) {
			return SysResult.error("该角色关联用户信息，不允许删除");
		}
		// 更新角色状态
		int updateNum = roleMapper.updateStatusByRoleId(id);
		if (updateNum < 1) {
			return SysResult.error("删除角色失败");
		}
		// 更新角色和权限清单状态
		rolePowerMapper.updateStatusByRoleId(id);
		return SysResult.ok();
	}

	/**
	 * 获取角色详情
	 */
	@Override
	public RoleDto query(Integer id, String type) {
		// 获取角色详情
		RoleDto role = roleMapper.query(id);
		if (!StringUtils.isEmpty(type) && type.equals("1")) {
			List<String> newPers = getNewPermissions(role.getPermissions());
			addModuleCode(newPers);
			role.setPermissions(newPers);
		}

		if (StringUtils.isEmpty(role)) {
			return null;
		}
		return role;
	}

	/**
	 * 添加模块code：APP端、项目端 @Title: addModuleCode @param newPers void @version
	 * V1.0 @throws
	 */
	private void addModuleCode(List<String> newPers) {
		if (StringUtils.isEmpty(newPers)) {
			return;
		}
		boolean isApp = false, isProject = false;
		for (String p : newPers) {
			if (!StringUtils.isEmpty(p)) {
				String modelId = p.split("-")[0];
				if (!StringUtils.isEmpty(modelId)) {
					if (Integer.parseInt(modelId) < 200 && !newPers.contains(ProjectTypeEnum._1.getKey())) {
						isProject = true;
					}
					if (Integer.parseInt(modelId) >= 200 && !newPers.contains(ProjectTypeEnum._2.getKey())) {
						isApp = true;
					}
				}
			}
		}
		if (isProject)
			newPers.add(ProjectTypeEnum._2.getKey());
		if (isApp)
			newPers.add(ProjectTypeEnum._1.getKey());
	}

	/**
	 * 添加模块code @Title: getNewPermissions @param permissions @return
	 * List<String> @version V1.0.1 @throws
	 */
	public static List<String> getNewPermissions(List<String> permissions) {
		List<String> newPers = new ArrayList<>();
		if (StringUtils.isEmpty(permissions)) {
			return newPers;
		}
		for (String p : permissions) {
			if (!StringUtils.isEmpty(p)) {
				String[] nums = p.split("-");
				if (nums.length > 0) {
					StringBuilder sb = new StringBuilder();
					for (int i = 0; i < nums.length - 1; i++) {
						sb.append(nums[i]);
						if (!newPers.contains(sb.toString())) {
							newPers.add(sb.toString());
						}
						sb.append("-");
					}
				}
			}
			newPers.add(p);
		}
		return newPers;
	}

	/**
	 * 启用禁用角色
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public SysResult status(Integer id, Integer status) {

		// 只能管理本层级级组织的角色
		Role role = roleMapper.selectByPrimaryKey(id);
		if (StringUtils.isEmpty(role)) {
			return SysResult.error("指定角色不存在");
		}
		if (role.getIsPublicRole() == 1) {
			return SysResult.error("通用角色不允许操作");
		}
		String teamId = String.valueOf(role.getTeamId());
		if (StringUtils.isEmpty(teamId)) {
			teamId = role.getFirstOrg();
		}
		Team team = teamMapper.selectByPrimaryKey(Integer.parseInt(teamId));
		if (StringUtils.isEmpty(team)) {
			return SysResult.error("组织不存在");
		}
		if (team.getIsActive() != 1) {
			return SysResult.error("该角色所属组织处于禁用状态，该角色不能启用");
		}

		if (role.getIsActive() == status) {
			return SysResult.ok();
		}
		// 启用禁用角色基本信息
		int roleNum = roleMapper.updateRoleBaseStatusByRoleId(id, status);
		if (roleNum < 1) {
			return SysResult.error("更新失败");
		}
		// 启用禁用角色和权限清单中间表
		rolePowerMapper.updateRolePowerStatusByRoleId(id, status);
		// // 更新角色和用户的中间表
		// userRoleMapper.updateUserRoleStatusByRoleId(id, status);
		// 更新组织和用户的中间表
		userTeamMapper.updateUserTeamStatusByRoleId(id, status);
		return SysResult.ok();
	}

	/**
	 * 角色列表 点击组织后，展示的所有角色包含：通用角色、本组织创建的角色 过滤通用角色用户为指定组织
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public SysResult list(RoleListDto roleListDto) {
		List<RoleDto> roleList = new ArrayList<>();
		Team org = teamMapper.selectByPrimaryKey(Integer.parseInt(roleListDto.getOrgId()));
		if (StringUtils.isEmpty(org)) {
			return SysResult.error("该组织不存在");
		}
		LoginDataVo loginDataVo = LocalManager.getVal(LocalManagerType.LOGIN_DATA);
		roleListDto.setFirstOrg(loginDataVo.getUser().getFirstOrg());
		PageHelper.startPage(roleListDto.getPage(), roleListDto.getPageSize());
		roleList = roleMapper.list(roleListDto);

		roleList.stream().forEach(r -> {
			if (r.getStatus() != r.getTeamStatus())
				if (!StringUtils.isEmpty(r.getTeamStatus()) && r.getTeamStatus().equals("2")) {
					r.setStatus("2");
				}
		});

		PageInfo pageInfo = new PageInfo(roleList);
		return SysResultByPage.ok(0, "SUCCESS", pageInfo.getList(), pageInfo.getTotal());
	}

	/**
	 * 查询某个用户对应的所有角色(用户模块查看角色)
	 * 
	 * @return
	 */
	@Override
	public List<Map<String, String>> findRoleByUserId(Map<String, Object> paramsMap) {
		List<Map<String, String>> list = userTeamMapper.findRoleByUserId(paramsMap);
		return list;
	}

	/**
	 * 查询登录选择身份组织/项目列表(登录选择身份列表)
	 */
	@Override
	public List<Map<String, String>> findIdentityByUserId(Map<String, Object> paramsMap) {
		List<Map<String, String>> list = userTeamMapper.findIdentityByUserId(paramsMap);
		return list;
	}

	/**
	 * 批量修改角色启用/禁用状态(主要用于启用/禁用组织下的所有角色)
	 * 
	 * @param code
	 * @param status 状态 1：启用 2：禁用 3：删除
	 */
	@Deprecated
	public void batchModifyRoleStatus(String code, String status) {
		// 查看组织及所有下级组织的所有角色
		List<RoleVo> roleList = roleMapper.findRoleLikeOrgCode(code);
		if (!roleList.isEmpty()) {
			// 批量更新角色状态
			roleMapper.batchUpdateRoleStatus(roleList, status);
			// 批量更新角色和权限清单状态
			rolePowerMapper.batchUpdateRolePowerStatus(roleList, status);
		}
		// 查询启用/禁用组织/项目在角色负责人/项目经理中的用户（更新user_team user_role中间表的状态）
		List<UserTeam> userTeamList = userTeamMapper.selectByTeamIdSetAndRoleId(code, status);
		// 更新user_team
		for (UserTeam userTeam : userTeamList) {
			userTeamMapper.updateUserTeamStatusById(userTeam.getId(), Integer.parseInt(status));
		}
	}

}
